﻿using System;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace studies
{
    public class Program
    {
        static void Main(string[] args)
        {
            Task parent = new Task(() =>
            {
                var cts = new CancellationTokenSource();
                var tf = new TaskFactory<Int32>(cts.Token,
                    TaskCreationOptions.AttachedToParent,
                    TaskContinuationOptions.ExecuteSynchronously,
                    TaskScheduler.Default);

                var childTasks = new[]
                {
                    tf.StartNew(()=> Sum(cts.Token , 10000)),
                    tf.StartNew(()=> Sum(cts.Token , 20000)),
                    tf.StartNew(()=> Sum(cts.Token , Int32.MaxValue))
                };

                for (Int32 task = 0; task < childTasks.Length; task++)
                {
                    childTasks[task].ContinueWith(t =>
                    {
                        cts.Cancel();
                    }, TaskContinuationOptions.OnlyOnFaulted);
                }

                tf.ContinueWhenAll(
                    childTasks,
                    completedTasks => completedTasks.Where(t => !t.IsFaulted && !t.IsCanceled).Max(t => t.Result),
                    CancellationToken.None)
                    .ContinueWith(t => { Console.WriteLine("the maximum is : " + t.Result); },
                    TaskContinuationOptions.ExecuteSynchronously);
            });

            parent.ContinueWith(p =>
            {
                StringBuilder sb = new StringBuilder();
                sb.Append("the following exception(s) ocured : " + Environment.NewLine);
                foreach (var e in p.Exception.Flatten().InnerExceptions)
                {
                    sb.Append(" " + e.GetType().ToString());
                }
                Console.WriteLine(sb.ToString());
            },
            TaskContinuationOptions.OnlyOnFaulted);
            parent.Start();



            Console.Read();
        }


        public static Int32 Sum(CancellationToken ct, Int32 n)
        {
            Int32 sum = 0;
            for (; n > 0; n--)
            {
                ct.ThrowIfCancellationRequested();
                checked
                {
                    sum += n;
                }
            }
            return sum;
        }
    }
}
